package com.qf.service.impl;

import com.qf.service.SearchService;
import com.qf.util.ElasticsearchUtil;
import com.qf.vo.LayUITableVO;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.BoostingQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class SearchServiceImpl implements SearchService {

    private RestHighLevelClient client = ElasticsearchUtil.client();

    @Override
    public List<Map> termQuery(String index, String type, String field, String value) throws IOException {
        //1. 创建request
        SearchRequest request = new SearchRequest();

        //2. 给request赋值
        request.indices(index);
        request.types(type);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery(field,value));
        request.source(sourceBuilder);

        //3. 通过client执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4. 通过resp拿到返回结果source
        List<Map> result = new ArrayList<>();
        for (SearchHit hit : resp.getHits().getHits()) {
            result.add(hit.getSourceAsMap());
        }

        //5. 返回
        return result;
    }

    @Override
    public List<Map> termsQuery(String index, String type, String field, String... values) throws IOException {
        //1. 创建request
        SearchRequest request = new SearchRequest();

        //2. 给request赋值
        request.indices(index);
        request.types(type);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termsQuery(field,values));
        request.source(sourceBuilder);

        //3. 通过client执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4. 通过resp拿到返回结果source
        List<Map> result = new ArrayList<>();
        for (SearchHit hit : resp.getHits().getHits()) {
            result.add(hit.getSourceAsMap());
        }

        //5. 返回
        return result;
    }

    @Override
    public LayUITableVO<Map> matchAllQuery(String index, String type, int page, int size) throws IOException {
        //1. 创建request
        SearchRequest request = new SearchRequest();

        //2. 给request赋值
        request.indices(index);
        request.types(type);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.from((page - 1) * size);
        sourceBuilder.size(size);
        request.source(sourceBuilder);

        //3. 通过client执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4. 通过resp拿到返回结果source
        LayUITableVO<Map> vo = new LayUITableVO<Map>();
        vo.setCount(resp.getHits().getTotalHits());

        List<Map> data = new ArrayList<>();
        for (SearchHit hit : resp.getHits().getHits()) {
            data.add(hit.getSourceAsMap());
        }
        vo.setData(data);
        vo.setCode(0);
        vo.setMsg("");
        //5. 返回
        return vo;
    }

    @Override
    public List<Map> matchQuery(String index, String type, String field, String value) throws IOException {
        //1. 创建request
        SearchRequest request = new SearchRequest();

        //2. 给request赋值
        request.indices(index);
        request.types(type);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchQuery(field,value));
        request.source(sourceBuilder);

        //3. 通过client执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4. 通过resp拿到返回结果source
        List<Map> result = new ArrayList<>();
        for (SearchHit hit : resp.getHits().getHits()) {
            result.add(hit.getSourceAsMap());
        }

        //5. 返回
        return result;
    }

    @Override
    public LayUITableVO<Map> boolQuery(String index, String type, int page, int size) throws IOException {
        //1. request
        SearchRequest request = new SearchRequest();

        //2. 封装request
        //2.1 设置index,type
        request.indices(index);
        request.types(type);
        //2.2  创建SearchSourceBuilder
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //2.3 设置from,size
        sourceBuilder.from((page - 1) * size);
        sourceBuilder.size(size);
        //2.4 查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//        # 查询省份为武汉或者北京
        boolQuery.should(QueryBuilders.termQuery("province","武汉"));
        boolQuery.should(QueryBuilders.termQuery("province","北京"));
//        # 运营商不是联通
        boolQuery.mustNot(QueryBuilders.termQuery("operatorId","2"));
//        # smsContent中包含中国和平安
        boolQuery.must(QueryBuilders.matchQuery("smsContent","中国"));
        boolQuery.must(QueryBuilders.matchQuery("smsContent","平安"));
        sourceBuilder.query(boolQuery);
        //2.5 将SearchSourceBuilder赋值给Request
        request.source(sourceBuilder);

        //3. 执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4. 封装LayUITableVO<Map>
        LayUITableVO<Map> vo = new LayUITableVO<>();
        vo.setCode(0);
        vo.setMsg("");
        vo.setCount(resp.getHits().getTotalHits());
        List<Map> data = new ArrayList<>();
        for (SearchHit hit : resp.getHits().getHits()) {
            data.add(hit.getSourceAsMap());
        }
        vo.setData(data);

        //5. 返回
        return vo;
    }

    @Override
    public List<Map> boostingQuery(String index, String type) throws IOException {
        //1. 创建request
        SearchRequest request = new SearchRequest();

        //2. 给request赋值
        request.indices(index);
        request.types(type);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(
                QueryBuilders.boostingQuery(
                    QueryBuilders.matchQuery("smsContent", "中国"),
                    QueryBuilders.matchQuery("smsContent", "移动,联通,电信")
                ).negativeBoost(0.1F));
        request.source(sourceBuilder);

        //3. 通过client执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4. 通过resp拿到返回结果source
        List<Map> result = new ArrayList<>();
        for (SearchHit hit : resp.getHits().getHits()) {
            result.add(hit.getSourceAsMap());
        }

        //5. 返回
        return result;
    }

    @Override
    public List<Map<String, HighlightField>> highLightQuery(String index, String type) throws IOException {
        //1. 创建request
        SearchRequest request = new SearchRequest();

        //2. 给request赋值
        //2.1 索引和类型
        request.indices(index);
        request.types(type);

        //2.2 查询条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.termQuery("corpName","中国平安保险有限公司"));
        boolQuery.must(QueryBuilders.matchQuery("smsContent","中国平安保险有限公司"));
        sourceBuilder.query(boolQuery);

        //2.3 高亮
        HighlightBuilder highLightBuilder = new HighlightBuilder();
        highLightBuilder.fragmentSize(50);
        highLightBuilder.preTags("<span style='color:red;'>");
        highLightBuilder.postTags("</span>");
        highLightBuilder.field("corpName");
        highLightBuilder.field("smsContent");
        sourceBuilder.highlighter(highLightBuilder);

        //2.4 给request设置sourceBuilder
        request.source(sourceBuilder);

        //3. 通过client执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4. 通过resp拿到返回结果source
        List<Map<String, HighlightField>> list = new ArrayList<>();
        for (SearchHit hit : resp.getHits().getHits()) {
            list.add(hit.getHighlightFields());
        }

        //5. 返回
        return list;
    }
}
